import {
  Controller,
  UseGuards,
  UploadedFile,
  BadRequestException,
  Post,
  Get,
  Param,
  Req,
  Delete,
} from '@nestjs/common';
import {
  Crud,
  CrudController,
  Override,
  ParsedRequest,
  CrudRequest,
  ParsedBody,
} from '@nestjsx/crud';
import { ApiTags, ApiBearerAuth, ApiConsumes } from '@nestjs/swagger';
import { deserializeArray } from 'class-transformer';
import { Album, Artist, Song, AlbumEdition } from '../entities';
import { AlbumsService } from '../services';
import { UserRole, FileStoragePath } from '@/enum';
import { Roles } from '@/decorators/roles.decorator';
import { AuthGuard, RolesGuard } from '@/guards';
import { FileUtils } from '@/utils';
import { RequestDtoRelationTransformer } from '@/interfaces';
import { User } from '@/modules/users/entities/user.entity';

@Crud({
  model: {
    type: Album,
  },
  query: {
    limit: 25,
    maxLimit: 100,
    join: {
      belongsToArtists: {},
      hasProducers: {},
      hasSongs: {},
      'hasSongs.belongsToArtists': {
        alias: 'artistsOfSongs',
      },
      editions: {},
      favByUsers: {},
    },
  },
  routes: {
    updateOneBase: {
      // decorators: [
      //   UseGuards(AuthGuard, RolesGuard),
      //   Roles(UserRole.ADMIN),
      //   ApiBearerAuth(),
      // ],
      interceptors: [
        FileUtils.singleFileUploader(
          'coverImage',
          ['image'],
          FileStoragePath.LIBRARY_IMAGES,
        ),
      ],
    },
    replaceOneBase: {
      decorators: [
        UseGuards(AuthGuard, RolesGuard),
        Roles(UserRole.ADMIN),
        ApiBearerAuth(),
      ],
    },
    deleteOneBase: {
      decorators: [
        UseGuards(AuthGuard, RolesGuard),
        Roles(UserRole.ADMIN),
        ApiBearerAuth(),
      ],
    },
    createOneBase: {
      // decorators: [
      //   UseGuards(AuthGuard, RolesGuard),
      //   Roles(UserRole.ADMIN),
      //   ApiBearerAuth(),
      // ],
      interceptors: [
        FileUtils.singleFileUploader(
          'coverImage',
          ['image'],
          FileStoragePath.LIBRARY_IMAGES,
        ),
      ],
    },
    createManyBase: {
      decorators: [
        UseGuards(AuthGuard, RolesGuard),
        Roles(UserRole.ADMIN),
        ApiBearerAuth(),
      ],
    },
  },
})
@ApiTags('albums')
@Controller('resources/albums')
// eslint-disable-next-line prettier/prettier
export class AlbumsController implements CrudController<Album>, RequestDtoRelationTransformer<Album> {
  constructor(public service: AlbumsService) {}

  get base(): CrudController<Album> {
    return this;
  }

  dtoRelationTransform(dto: Album) {
    try {
      if (typeof dto.belongsToArtists === 'string') {
        dto.belongsToArtists = deserializeArray(Artist, dto.belongsToArtists);
      }
      if (typeof dto.hasProducers === 'string') {
        dto.hasProducers = deserializeArray(Artist, dto.hasProducers);
      }
      if (typeof dto.hasSongs === 'string') {
        dto.hasSongs = deserializeArray(Song, dto.hasSongs);
      }
      if (typeof dto.editions === 'string') {
        dto.editions = deserializeArray(AlbumEdition, dto.editions);
      }
      if (typeof dto.favByUsers === 'string') {
        dto.favByUsers = deserializeArray(User, dto.favByUsers);
      }
    } catch (e) {
      if (e instanceof SyntaxError) {
        throw new BadRequestException(e.message, e.name);
      }
      throw new BadRequestException();
    }

    return dto;
  }

  /**
   * 查询用户是否喜欢接口
   * @param id album id
   * @param req request
   */
  @UseGuards(AuthGuard)
  @Get(':id/fav')
  checkFav(@Param() id: number, @Req() req) {
    return this.service.checkFav(id, req.user.id);
  }

  /**
   * 用户喜欢接口
   * @param id album id
   * @param req request
   */
  @UseGuards(AuthGuard)
  @Post(':id/fav')
  setFav(@Param() id: number, @Req() req) {
    return this.service.setFav(id, req.user.id);
  }

  /**
   * 用户取消喜欢接口
   * @param id album id
   * @param req request
   */
  @UseGuards(AuthGuard)
  @Delete(':id/fav')
  removeFav(@Param() id: number, @Req() req) {
    return this.service.removeFav(id, req.user.id);
  }

  @UseGuards(AuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN)
  @ApiBearerAuth()
  @ApiConsumes('multipart/form-data')
  @Override()
  createOne(
    @ParsedRequest() req: CrudRequest,
    @ParsedBody() dto: Album,
    @UploadedFile() coverImage?: Express.Multer.File,
  ) {
    dto = this.dtoRelationTransform(dto);
    if (coverImage) {
      dto.coverImage = coverImage.path;
    }
    return this.base.createOneBase(req, dto);
  }

  @UseGuards(AuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN)
  @ApiBearerAuth()
  @ApiConsumes('multipart/form-data')
  @Override()
  updateOne(
    @ParsedRequest() req: CrudRequest,
    @ParsedBody() dto: Album,
    @UploadedFile() coverImage?: Express.Multer.File,
  ) {
    dto = this.dtoRelationTransform(dto);
    if (coverImage) {
      dto.coverImage = coverImage.path;
    }
    return this.base.updateOneBase(req, dto);
  }
}
